package webServices;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;

import javax.imageio.ImageIO;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

import user.UserDataBase;

import basicShapes.Arc;
import basicShapes.Ellipse;
import basicShapes.Line;
import basicShapes.Point;
import basicShapes.Polygon;
import basicShapes.Rectangle;

import image.Image;

@WebService(name="photoshop", targetNamespace="http://photoshop/")
public class Draw {
        
    @WebMethod(operationName="logIn")
    public Boolean logIn(String login) {
            return UserDataBase.getInstance().isAccessGranted(login);
    }
    
    @WebMethod(operationName="getImageShapes")
    public ArrayList<String> getImageShapes(String file){
        File f = new File(file+".xml");
        if(f.exists()) {
            Image i = unmarshaliseImage(file);
            ArrayList<String> shapes = new ArrayList<String>();
            for (Image im : i.getShapes()){
                    shapes.add(im.toString()+";"+im.getName());
            }                       
            return shapes;                       
        }
        else {
            return null;
        }                       
    }
    
	@WebMethod(operationName="ping")
	public boolean ping() {
		return true;
	}
    
    @WebMethod(operationName="getMyImagesName")
    public ArrayList<String> getMyImagesName(String login) {
        ArrayList<String> imageFiles = new ArrayList<String>();
        File[] files = null; 
        File directoryToScan = new File("."); 
        files = directoryToScan.listFiles(); 
        for(File f : files) {
            if(f.getAbsolutePath().endsWith(".xml")) {
                Image i = unmarshaliseImage(f.getAbsolutePath().substring(0, f.getAbsolutePath().length()-4));
                if(i.getOwner().equalsIgnoreCase(login)) {
                	imageFiles.add(f.getName());
                }
            }
        }
        return imageFiles;
    }
    
    @WebMethod(operationName="getAllImagesName")
    public ArrayList<String> getAllImagesName() {
        ArrayList<String> imageFiles = new ArrayList<String>();
        File[] files = null; 
        File directoryToScan = new File("."); 
        files = directoryToScan.listFiles(); 
        for(File f : files) {
            if(f.getAbsolutePath().endsWith(".xml")) {
            	imageFiles.add(f.getName());
            }
        }
        return imageFiles;
    }
    
    @WebMethod(operationName="createImage")
    public Image createImage(String name, String owner) {
        return new Image(name, owner);
    }
    
    @WebMethod(operationName="addArc")
    public void addArc(String file, int x, int y, int w, int h, int s, int e, int t) {
        File f = new File(file+".xml");
        if(f.exists()) {
            Image i = unmarshaliseImage(file);
            Image newImage = new Arc(x, y, w, h, s, e, t);
            newImage.setName("toto");
            i.getShapes().add(newImage);
            marshaliseImage(i);
        }      
    }
    
    @WebMethod(operationName="addEllipse")
    public void addEllipse(String file, int x, int y, int w, int h) {
        File f = new File(file+".xml");
        if(f.exists()) {
        	Image i = unmarshaliseImage(file);
            i.getShapes().add(new Ellipse(x, y, w, h));
            marshaliseImage(i);
            updateFiles(file);
        }
    }
    
    @WebMethod(operationName="addLine")
    public void addLine(String file, int x1, int y1, int x2, int y2) {
        File f = new File(file+".xml");
        if(f.exists()) {
            Image i = unmarshaliseImage(file);
            i.getShapes().add(new Line(x1, y1, x2, y2));
            marshaliseImage(i);
            updateFiles(file);
        } 
    }
    
    @WebMethod(operationName="addPolygon")
    public void addPolygon(String file, ArrayList<Integer> pointsX, ArrayList<Integer> pointsY, int size) {
        File f = new File(file+".xml");
        if(f.exists()) {
            Image i = unmarshaliseImage(file);
            int tabX[] = new int[size]; 
           	int tabY[] = new int[size];
            for (int j=0;j<size;j++){
            	tabX[j]=pointsX.get(j);
            	tabY[j]=pointsY.get(j);
            }
            i.getShapes().add(new Polygon(tabX, tabY, size));
            marshaliseImage(i);
            updateFiles(file);
        }
    }
    
    @WebMethod(operationName="addRectangle")
    public void addRectangle(String file, int x, int y, int w, int h) {
        File f = new File(file+".xml");
        if(f.exists()) {
            Image i = unmarshaliseImage(file);
            i.getShapes().add(new Rectangle(x, y, w, h));
            marshaliseImage(i);
            updateFiles(file);
        }
    }
    
    @WebMethod(operationName="addImage")
    public void addImage(String file_dest, String new_file) {
        File f = new File(new_file+".xml");
        if(f.exists()) {
            Image i = unmarshaliseImage(file_dest);
            Image new_i = unmarshaliseImage(new_file);
            i.getShapes().add(new_i);
            marshaliseImage(i);
        }
    }
    
    @WebMethod(operationName="getXML")
    public String getXML(String image) {
        String ret = "";
        try {
            FileReader fr;
            fr = new FileReader(image+".xml"); 
            BufferedReader br = new BufferedReader(fr); 
            String s; 
            boolean i=true;
            while((s = br.readLine()) != null) { 
            	if (i ){ret += s;i=false;}
            	else ret += "\n"+s;
                    
            } 
            fr.close(); 
        } catch(Exception e) {
        	e.printStackTrace();
        }
        return ret;
    }
    
    public static Image unmarshaliseImage(String file) {
        try {
            /* UNMARSHALLER XML TO JAVA */
            JAXBContext context = JAXBContext.newInstance(Image.class, 
                                                          	Line.class,
                                                            Ellipse.class,
                                                            Arc.class,
                                                            Polygon.class,
                                                            Rectangle.class,
                                                            Point.class);
            Unmarshaller u = context.createUnmarshaller();
            Image i_lue = (Image) u.unmarshal(new File(file+".xml"));
            return i_lue;
        } catch(Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    
    public void marshaliseImage(Image i) {
        try {
            /* MARSHALLER JAVA TO XML */
            JAXBContext context = JAXBContext.newInstance(Image.class, 
                                                            Line.class,
                                                            Ellipse.class,
                                                            Arc.class,
                                                            Polygon.class,
                                                            Rectangle.class,
                                                            Point.class);
            Marshaller m = context.createMarshaller();
            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
            m.marshal(i, new File(i.getName()+".xml"));
        } catch(Exception e) {
                e.printStackTrace();
        }
    }
    
    @WebMethod(operationName="getImagePng")
    public byte[] getImagePng(String image) {
        byte[] imageInByte = null;
        try {
            // UNMARSHALLER XML TO JAVA 
            JAXBContext context = JAXBContext.newInstance(Image.class, 
                                                            Line.class,
                                                            Ellipse.class,
                                                            Arc.class,
                                                            Polygon.class,
                                                            Rectangle.class,
                                                            Point.class);
            Unmarshaller u = context.createUnmarshaller();                  
            Image i_lue = (Image) u.unmarshal(new File(image+".xml"));
            i_lue.drawImage();
            
            // Creation of the read image
            File outputfile = new File(i_lue.getName()+"_server_side.png");
            ImageIO.write(i_lue.getBi(), "png", outputfile);
            
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write( i_lue.getBi(), "png", baos );
            baos.flush();
            imageInByte = baos.toByteArray();
            baos.close();                    
        } catch(Exception e) {
                e.printStackTrace();
        }
        return imageInByte;
    }
    
    @WebMethod(operationName="removeItem")
    public void removeItem(String image, String item_to_be_removed) {
        Image i = unmarshaliseImage(image);
        Image imageToRemove = null;
        for(Image img : i.getShapes()) {
            if(img.getName().equalsIgnoreCase(item_to_be_removed)) {
                imageToRemove = img;
            }
        }
        i.getShapes().remove(imageToRemove);
        marshaliseImage(i);
        updateFiles(image);
    }
    
    @WebMethod(operationName="deleteItem")
    public void deleteItem(String image) {
        File[] files = null; 
        File directoryToScan = new File("."); 
        files = directoryToScan.listFiles(); 
        
        for(File f : files) {
            if(f.getAbsolutePath().endsWith(".xml")) {      
                Image i = unmarshaliseImage(f.getAbsolutePath().substring(0, f.getAbsolutePath().length()-4));
                int cpt = 0;
                ArrayList<Integer> indexes = new ArrayList<Integer>();
                for(Image img : i.getShapes()) {
                    if(img.getName().equalsIgnoreCase(image)) {
                        System.out.println(i.getName()+" has been updated");
                        indexes.add(cpt);
                    }
                    cpt++;
                }
                for(int k=0; k<indexes.size(); k++) {
                    i.getShapes().remove(i.getShapes().get(indexes.get(k)));
                }
                marshaliseImage(i);
            }
        }
        updateFiles(image);
        File f = new File(image+".xml");
        f.delete();
        f = new File(image+".png");
        f.delete();
    }
        
    // Cette fonction permet de mettre à jour les images composées d'autres images
    public void updateFiles(String file) {
        File[] files = null; 
        File directoryToScan = new File("."); 
        files = directoryToScan.listFiles(); 
        Image newImage = unmarshaliseImage(file);
        for(File f : files) {
            // Ici on met à jour les images
            if(f.getAbsolutePath().endsWith(".xml")) {      
                Image i = unmarshaliseImage(f.getAbsolutePath().substring(0, f.getAbsolutePath().length()-4));
                int cpt = 0;
                ArrayList<Integer> indexes = new ArrayList<Integer>();
                for(Image img : i.getShapes()) {
                    if(img.getName().equalsIgnoreCase(file)) {
                    	System.out.println(i.getName()+" has been updated");
                    	indexes.add(cpt);
                    }
                    cpt++;
                }
                for(int k=0; k<indexes.size(); k++) {
                    i.getShapes().set(indexes.get(k), newImage);
                    marshaliseImage(i);
                }
            }
        }
    }
}
